#include "subwidget_serial.h"
#include "ui_subwidget_serial.h"
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <QString>
#include <QDebug>
#include <QMessageBox>
#include <QTimer>
#include "util.h"

SubWidget_Serial::SubWidget_Serial(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SubWidget_Serial)
{
    ui->setupUi(this);

    Serial_init();

    m_is_serialport_ready = false;
    QTimer* timer = new QTimer(this);
    timer->start(1000);
    connect(timer, &QTimer::timeout, this,
            [=](){
                    if(m_is_serialport_ready)
                    {
                        qDebug()<<"发送数据。。。";
//                        char arr[] = {0x01, 0x03, 0x00, 0x12, 0x00, 0x01, 0x24, 0x0F};
//                        QByteArray data_arr;
//                        for(char temp:arr)
//                        {
//                            data_arr.append(temp);
//                        }
//                        send_message(data_arr);
                        QByteArray arr_moisture_sensor = Util::get().read_json("./json_rc/sensor.json", "sensor_th1");
                        send_message(arr_moisture_sensor);
                    }
                 });
    connect(m_SerialPort, &QSerialPort::readyRead, this,
            [=](){
                     double data = this->receive_message();
                     qDebug()<<"data: "<<data;
                     if(data!=NULL)
                     {
                         emit get_data(1, data);
                     }
                 }
            );
}

/**
 * @brief SubWidget_Serial::Serial_init 配置串口参数
 */
void SubWidget_Serial::Serial_init()
{
    //串口参数配置
    m_SerialPort = new QSerialPort;
    //自动搜索串口号并保存
    QStringList serialPortName;
    foreach (const QSerialPortInfo& info, QSerialPortInfo::availablePorts()) {          //foreach相当于将availablePorts中的每一项传给info，同时info也将其顺带着传给serialName
        serialPortName << info.portName();
        qDebug()<<info.portName()<<"================";
    }
    ui->comboBox_serialPort->addItems(serialPortName);

    connect(ui->comboBox_serialPort, &QComboBox::currentTextChanged, [=](){
        m_SerialPort->setPortName(ui->comboBox_serialPort->currentText());
    });
    m_SerialPort->setDataBits(QSerialPort::Data8);
    m_SerialPort->setStopBits(QSerialPort::OneStop);
    m_SerialPort->setParity(QSerialPort::NoParity);                                 //奇偶效验位
    m_SerialPort->setFlowControl(QSerialPort::NoFlowControl);
    m_SerialPort->setBaudRate(QSerialPort::Baud9600);
    //显示默认波特率9600
    ui->comboBox_Baud_rate->setCurrentIndex(2);

    //关闭串口
    m_SerialPort->close();
}

bool SubWidget_Serial::is_SerialPort_ready() const
{
    return m_is_serialport_ready;
}

/**
 * @brief SubWidget_Serial::receive_message 将得到的应答帧，通过data()切片成一个个字节，储存到char型容器中
 * @param data_value 返回测量结果
 */
double SubWidget_Serial::receive_message()
{
    QByteArray d = m_SerialPort->readAll();
    //目前应答帧有7字节
    const int data_frame_len = 7;
    char* dp = d.data();
    int bufferSize = d.size();          //返回里面有几个字节的数据，一个字节有8位，正好一个字节就是一个char，同时char是最小的存储单位，所以用char来存数据
    int index = 0;
    m_datafrm.clear();
    while (index < bufferSize)
    {
        m_datafrm.append(dp[index]);
        index++;
        if(m_datafrm.size() == data_frame_len)
        {
            m_datafrm.print();
            double data_value = dealMulty(m_datafrm);
            m_datafrm.clear();
            qDebug()<<"data_value: "<<data_value;
            return data_value;
        }
    }
    qDebug()<<"SubWidget_Serial::receive_message未收到数据";
    return 0;
}

/**
 * @brief SubWidget_Serial::deal (仅处理水分)处理传入的应答帧，获取目标水分值
 * @param datafrm 应答帧
 * @return humidty 得到水分值
 */
double SubWidget_Serial::deal(DataFrame datafrm)
{
    double humidty;
    humidty = ((double)(unsigned char)(datafrm[3]<<2)+(double)(unsigned char)datafrm[4])/10;         //让高位左移两位
    qDebug()<<"水分： "<<humidty;
    return humidty;
}

double SubWidget_Serial::dealMulty(DataFrame datafrm)
{
    switch(datafrm[0])
    {
    case 0x01:
        qDebug()<<"dealMulty: 处理电机数据";
        return NULL;
        break;
    case 0x02:
        qDebug()<<"dealMulty: 处理水分传感器数据";
        return deal(datafrm);
        break;
    default:
        qDebug()<<"dealMulty: 未收到正确数据";
        break;
    }
    return NULL;
}

void SubWidget_Serial::send_message(QByteArray d)
{
    if(m_SerialPort->isOpen())
    {
        m_SerialPort->write(d);
        qDebug()<<"Subwidget_serial send_message 写入数据"<<d.toHex();
    }
}

void SubWidget_Serial::slot_send_message(QByteArray d, QString mess)
{
    //qDebug()<<"subwidget_serial: 发送"<<d.toHex();
    if(mess!="")
    {
        qDebug()<<"subwidget_serial::slot_send_message: "<<mess;
    }
    send_message(d);
}

SubWidget_Serial::~SubWidget_Serial()
{
    delete ui;
}

void SubWidget_Serial::on_comboBox_serialPort_currentTextChanged(const QString &arg1)
{
    //设置串口
    m_SerialPort->setPortName(ui->comboBox_serialPort->currentText());
}

/**
 * @brief SubWidget_Serial::on_comboBox_Baud_rate_currentIndexChanged 波特率按钮变化会触发此槽
 * @param index 得到当前按钮停在第几个波特率选项上
 */
void SubWidget_Serial::on_comboBox_Baud_rate_currentIndexChanged(int index)
{
    switch(index){
        case 0:m_SerialPort->setBaudRate(QSerialPort::Baud2400);
        break;
        case 1:m_SerialPort->setBaudRate(QSerialPort::Baud4800);
        break;
        case 2:m_SerialPort->setBaudRate(QSerialPort::Baud9600);
        break;
        case 3:m_SerialPort->setBaudRate(QSerialPort::Baud38400);
        break;
        case 4:m_SerialPort->setBaudRate(QSerialPort::Baud115200);
        break;
    default:    m_SerialPort->setBaudRate(QSerialPort::Baud9600);
    }
}

void SubWidget_Serial::on_radioButton_close_clicked()
{
    if(!m_is_serialport_ready)
    {
        if(m_SerialPort->open(QIODevice::ReadWrite))
        {
            QMessageBox::information(this,"提示", "打开成功！");
            m_is_serialport_ready=true;
            return ;
        }
        else
        {
            QMessageBox::information(this,"提示", "打开失败！");
        }
        qDebug()<<"串口打开失败";
        m_is_serialport_ready = false;
    }
    else
    {
        m_SerialPort->close();
        QMessageBox::information(this,"提示", "串口关闭成功！");
        m_is_serialport_ready = false;
    }
}

/**
 * @brief SubWidget_Serial::SerialPort_poit 感觉不能将私有属性开放出去
 * @return
 */
const QSerialPort& SubWidget_Serial::get_mySerialPort() const
{
    return *(this->m_SerialPort);
}

SubWidget_Serial::DataFrame::DataFrame()
{
    datas.clear();
    datas.resize(16);
}

void SubWidget_Serial::DataFrame::append(char v)
{
    datas.push_back(v);
}

std::size_t SubWidget_Serial::DataFrame::size() const
{
    return datas.size();
}

char& SubWidget_Serial::DataFrame::operator[](std::size_t index)
{
    return datas[index];
}

const char& SubWidget_Serial::DataFrame::operator[](std::size_t index) const
{
    return datas[index];
}

void SubWidget_Serial::DataFrame::clear()
{
    datas.clear();
}

void SubWidget_Serial::DataFrame::print()
{
    for(char c : this->datas)
    {
        fprintf(stdout, "%02X", (int)c);
        //qDebug()<<(int)c;                     //这句就先不要了，这个是看看能不能用10进制显示这个char存的8个bit的数据
    }
    fprintf(stdout,"\n");
    fflush(stdout);
}
